[꼭대기 에]      IBatis 의 페이지 연구 --- sql 페이지

JPetStore 의 코드 를 보 았 을 때 페이지 처 리 는 주로 Paginated List 대상 으로 돌아 가 는 것 을 통 해 이 루어 진 것 으로 밝 혀 졌 다.CatalogService 클래스 에서
public PaginatedList getProductListByCategory(String categoryId) {       return productDao.getProductListByCategory(categoryId);     }   

페이지 를 나 누 는 것 은 데이터베이스 형 시스템 을 조작 하 는 데 자주 발생 하 는 문제 이다.페이지 를 나 누 어 실현 하 는 방법 은 매우 많 지만 효율 의 차 이 는 매우 크다.아이 바 티 스 는 어떤 방식 으로 이 페이지 를 실현 하 였 습 니까?실현 부분 보기:
되 돌아 오 는 PaginatedList 는 실제 인터페이스 입 니 다. 이 인 터 페 이 스 를 실현 하 는 것 은 PaginatedDataList 류 의 대상 입 니 다. PaginatedDataList 류 를 보면 페이지 를 넘 길 때마다 다음 함수 가 호출 됩 니 다.
private List getList(int idx, int localPageSize) throws SQLException {       return sqlMapExecutor.queryForList(statementName, parameterObject, (idx) * pageSize, localPageSize);     }   

... 때문에
public interface SqlMapClient extends SqlMapExecutor, SqlMapTransactionManager {……}   

그래서 실제 호출 순 서 는 다음 과 같다.
SqlMapClientImpl.queryForPaginatedList->SqlMapSessionImpl.queryForPaginatedList   ->SqlMapExecutorDelegate.queryForPaginatedList->GeneralStatement.executeQueryForList   ->GeneralStatment.executeQueryWithCallback->GeneralStatment.executeQueryWithCallback   ->SqlExecutor.executeQuery->SqlExecutor.handleMultipleResults()->SqlExecutor.executeQuery-> handleResults   

페이지 별 처리 함 수 는 다음 과 같다.
private void handleResults(RequestScope request, ResultSet rs, int skipResults, int maxResults, RowHandlerCallback callback) throws SQLException {       try {         request.setResultSet(rs);         ResultMap resultMap = request.getResultMap();         if (resultMap != null) {           // Skip Results           if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {             if (skipResults > 0) {               rs.absolute(skipResults);             }           } else {             for (int i = 0; i < skipResults; i++) {               if (!rs.next()) {                 return;               }             }           }               // Get Results           int resultsFetched = 0;           while ((maxResults == SqlExecutor.NO_MAXIMUM_RESULTS || resultsFetched < maxResults) && rs.next()) {             Object[] columnValues = resultMap.resolveSubMap(request, rs).getResults(request, rs);             callback.handleResultObject(request, columnValues, rs);             resultsFetched++;           }         }       } finally {         request.setResultSet(null);       }     } 

이 를 통 해 알 수 있 듯 이 iBatis 의 페이지 는 주로 jdbcdriver 의 어떻게 실현 되 는 지, rs. absolute (skipResults) 를 지원 하 는 지 에 의존 합 니 다.그것 은 결코 좋 은 페이지 방식 이 아니다.조건 에 맞 는 모든 기록 을 꺼 내 ResultSet 대상 에 저장 한 다음 absolute 방법 으로 포 지 셔 닝 을 하여 페이지 를 나 누 어야 합 니 다.기록 수가 비교적 많 을 때 (예 를 들 어 10 만 개) 전체적인 조회 속 도 는 매우 느 려 질 것 이다.그래서 페이지 를 나 누 는 것 은 sql 문 구 를 직접 조작 하 는 것 을 고려 해 야 한다.물론 소량 은 아이 바 티 스 의 페이지 모드 를 사용 할 수 있다.일반 페이지 의 sql 문 구 는 데이터 뱅 크 의 구체 적 인 실현 과 관계 가 있다.
mysql:   select * from A limit startRow,endRow   oracle:   select b.* from (select a.*,rownum as linenum from (select * from A) a where rownum <= endRow) b where linenum >= startRow   

Hibernate 의 Oracle 페이지 는 RowNum 의 Sql 문 구 를 조합 하여 완성 한 것 입 니 다.참조 코드 는 다음 과 같 습 니 다.
public String createOraclePagingSql(String sql, int pageIndex, int pageSize){               int m = pageIndex * pageSize;               int n = m + pageSize;               return "select * from ( select row_.*, rownum rownum_ from ( " + sql                       + " ) row_ where rownum <= " + n                        + ") where rownum_ > " + m;           } 

종합 적 으로 소량 (< 2w) 은 ibatis 자체 가 가지 고 있 는 페이지 류 를 사용 할 수 있 습 니 다. 대량의 양 은 sql 을 직접 조작 할 수 있 습 니 다. 물론 이 sql 을 스스로 포장 하거나 가방 에 포장 할 수 있 습 니 다.패키지 패키지 의 예제 코드 는 다음 과 같다. 페이지 기능 이 포 함 된 Oracle Package
create or replace package body FMW_FY_HELPER is  PROCEDURE GET_DATA(pi_sql in varchar,pi_whichpage in integer,pi_rownum in integer,  po_cur_data out cur_DATA,po_allrownum out integer,pio_succeed in out integer)  as   v_cur_data cur_DATA;  v_cur_temp cur_TEMP;  v_temp integer;  v_sql varchar(5000);  v_temp1 integer;  v_temp2 integer;  begin  pio_succeed := 1;  v_sql := 'select count(''a'') from ( ' || pi_sql || ')';  execute immediate v_sql into v_temp;    po_allrownum:=ceil(v_temp/pi_rownum);    v_sql := '';  v_temp :=pi_whichpage*pi_rownum + 1;  v_temp1:=(pi_whichpage-1)*pi_rownum + 1;  v_temp2:=pi_whichpage*pi_rownum;  v_sql:= 'select * from (select rownum as rn,t.* from (' || pi_sql ||') t where rownum<' || to_char(v_temp) || ')  where rn between ' || to_char(v_temp1) || ' and ' || to_char(v_temp2);  open v_cur_data for v_sql;  if v_cur_data %notfound  then  pio_succeed:=-1;  return;  end if;  po_cur_DATA := v_cur_data;  end;

좋은 웹페이지 즐겨찾기